/*
 * File:   ChessMove.cpp
 * Author: Michael Ziminsky
 *
 * Created on February 26, 2011, 10:26 PM
 */

#include "ChessMove.h"
#include "placepiece.h"
#include "movepiece.h"
#include "model/pieces/allpieces.h"
#include <iostream>
#include <boost/make_shared.hpp>

inline int ctoi(char c)
{
    return c - '0';
}

ChessMove::ChessMove(const std::string& str)
{
    boost::sregex_iterator s(str.begin(), str.end(), ChessMove::pattern);
    boost::sregex_iterator e;
    globals::movePtr tmp;
    for (; s != e; s++)
    {
        const boost::smatch& match = *s;
        using std::string;
        if (match.length(PLACEPATTERN))
        {
            char p = ((string)match[PIECETYPE])[0];
            bool l = tolower(((string)match[TEAM])[0]) == 'l';

            int r = ctoi(((string)match[PLACEROW])[0]);
            char c = ((string)match[PLACECOL])[0];

            tmp = boost::make_shared<PlacePiece>(ChessMove::charToPiece(p, l), model::Location(c, r));
        }
        else if (match.length(MOVEPATTERN))
        {
            int fr = ctoi(((string)match[MOVEFROMROW])[0]);
            char fc = ((string)match[MOVEFROMCOL])[0];

            int tr = ctoi(((string)match[MOVETOROW])[0]);
            char tc = ((string)match[MOVETOCOL])[0];

            tmp = boost::make_shared<MovePiece>(model::Location(fc, fr), model::Location(tc, tr), match.length(MOVECAPTURE));
        }
        else tmp = boost::make_shared<InvalidMove>(match[INVALID]);

        if (tmp)
        {
            moves.push_back(tmp);
            tmp.reset();
        }
    }
}

void ChessMove::execute(model::ChessBoard& b)
{
    for (std::list<globals::movePtr>::const_iterator i = moves.begin(); i != moves.end(); i++)
        (*i)->execute(b);
}

void ChessMove::undo(model::ChessBoard & b)
{
    for (std::list<globals::movePtr>::const_reverse_iterator i = moves.rbegin(); i != moves.rend(); i++)
        (*i)->undo(b);
}

ChessMove::InvalidMove::InvalidMove(const std::string& move) : move(move) {}

void ChessMove::InvalidMove::execute(model::ChessBoard &)
{
    std::cerr << "Invalid Move: " << move << std::endl;
}

void ChessMove::InvalidMove::undo(model::ChessBoard &) {}

globals::cPiece ChessMove::charToPiece(char c, bool light)
{
    globals::cPiece p;
    switch (toupper(c))
    {
        using namespace model::piece;
    case 'Q':
        p = boost::make_shared<Queen>(light);
        break;
    case 'K':
        p = boost::make_shared<King>(light);
        break;
    case 'R':
        p = boost::make_shared<Rook>(light);
        break;
    case 'N':
        p = boost::make_shared<Knight>(light);
        break;
    case 'B':
        p = boost::make_shared<Bishop>(light);
        break;
    case 'P':
        p = boost::make_shared<Pawn>(light);
        break;
    }
    return p;
}

const boost::regex ChessMove::pattern("\\b(([KQNRBP])([ld])([A-H])([1-8]))\\b|"
    "\\b(([A-H])([1-8])\\s([A-H])([1-8])([*])?(?!\\S))|"
    "(\\S+)", boost::regbase::icase);
